/******************************************************************************
** 
** Break the long string into shorter ones. 
** 
** File name:	break_long_string.c
** Compilation:	cc break_long_string.c -o break_long_string
** Execution:	./break_long_string
** 
** Description:
** Reads the input string and breaks it into several shorter ones (maximum  
** length is set in the code), replaces excessive spaces and tabs before the 
** break position.
** 
******************************************************************************/
#include <stdio.h>
#include <limits.h>

#define MAX_LINE_LENGTH USHRT_MAX
#define TAB_SYMBOL '\t'
#define SPACE_SYMBOL ' '
#define NEWLINE_SYMBOL '\n'
#define ENDLINE_SYMBOL '\0'

#define COLUMN_LENGTH 50

int GetLine(char line[], unsigned short int maxLength);
void CopyLine(char source[], char destination[]); // actually is not used in this program.
int StripSpaces(char line[], int length);


int main()
{
    unsigned short int base;
    unsigned short int limitPosition;
    unsigned short int currentStringLength;
    unsigned short int i;
    unsigned short int lastSpacePosition;
    short int stillSpace;
    char string[MAX_LINE_LENGTH];

    while ((currentStringLength = GetLine(string, MAX_LINE_LENGTH)) != 0) {
        currentStringLength = StripSpaces(string, currentStringLength);
        if (currentStringLength <= COLUMN_LENGTH) {
            printf("%s", string);
        } else {
            // Main algorithm
            base = 0;
            limitPosition = COLUMN_LENGTH;
            lastSpacePosition = 0;
            stillSpace = 0;
            // Dividing long string into chunks of "COLUMN_LENGTH", working with them.
            while (limitPosition < currentStringLength) {
                // Defining which space symbol position is the closest one:
                for (i=base; i<=limitPosition; ++i) {
                    if ( (string[i] == SPACE_SYMBOL) || (string[i] == TAB_SYMBOL) ) {
                        if (stillSpace == 0) {
                            lastSpacePosition = i;
                            stillSpace = 1;
                        } else {
                            // do nothing
                        }
                    } else {
                        stillSpace = 0;
                    }
                }
                // Now we got it in lastSpacePosition.
                // For the words that are bigger than cloumn width:
                if (lastSpacePosition <= base) {
                    lastSpacePosition = base + COLUMN_LENGTH;
                }
                // We can print a column's string now.
                for (i=base; i<lastSpacePosition; ++i) {
                    putchar(string[i]);
                }
                putchar(NEWLINE_SYMBOL);
                // Now we must find next base position for the next iteration.
                i = lastSpacePosition;
                while ( (string[i] == SPACE_SYMBOL) || (string[i] == TAB_SYMBOL) || (string[i] == NEWLINE_SYMBOL) ) {
                    ++i;
                }
                // We have it. New start and end points:
                base = i;
                limitPosition = i + COLUMN_LENGTH;
            }
            // New "limitPosition" is greater tha the string's length - we must just print the rest of the string, from "base".
            for (i=base; i<=currentStringLength; ++i) {
                putchar(string[i]);
            }
            // Done. Next string awaits.
        }
    }

    return 0;
}


// GetLine: Reads one line from the input and stores it in the array, returns line length.
int GetLine(char line[], unsigned short int maxLength)
{
    char c;
    unsigned short int i;

    for (i=0; i<maxLength && (c=getchar()) != EOF && c != NEWLINE_SYMBOL; ++i) {
        line[i] = c;
    }
    if (c == NEWLINE_SYMBOL) {
        line[i] = c;
        ++i;
    }
    line[i] = ENDLINE_SYMBOL;
    return i;
}


// CopyLine: Copies one char array to another.
void CopyLine(char source[], char destination[])
{
    unsigned short int i;

    i = 0;
    while ((destination[i] = source[i]) != ENDLINE_SYMBOL) {
        ++i;
    }
}


// StripSpaces: Returns new string length (with '\n' counted), '\0' must be put at [length] position of the source string.
int StripSpaces(char line[], int length)
{
    --length;
    --length;
    while ((line[length] == TAB_SYMBOL) || (line[length] == SPACE_SYMBOL)) {
        --length;
    }
    ++length;
    line[length] = NEWLINE_SYMBOL;
    ++length;
    line[length] = ENDLINE_SYMBOL;
    return length;
}
